package org.example.equip.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.example.commons.common.Result;
import com.example.commons.entity.Equip;
import com.example.commons.entity.Personality;
import com.example.commons.entity.dto.EquipStats;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.example.equip.service.EquipService;
import org.example.equip.service.PersonalityService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;

/**
 * @program: authority-v3.0.7
 * @ClassName:EquipController
 * @description: EquipController前端控制器
 * @author:dyy
 * @Version 3.0
 **/

@Tag(name = "装备列表 前端控制器")
@RestController
@RequestMapping("/equip")
public class EquipController {
    @Resource
    private EquipService equipService;

    @Resource
    private PersonalityService personalityService;


    /**
     * 新增
     *
     * @param equip
     * @return
     */
    @Operation(summary = "新增")
    @PostMapping
    public Result save(@RequestBody Equip equip) {
        // 新增校验逻辑
        if (checkEquipConflict(equip.getBelongSuit(), equip.getBelong(), null)) {
            return Result.error("该套装的该部位只能添加一件装备");
        }
        return Result.success(equipService.save(equip));
    }


    /**
     * 修改
     *
     * @param equip
     * @return
     */
    @Operation(summary = "修改")
    @PutMapping("/{id}")
    public Result update(@PathVariable Long id, @RequestBody Equip equip) {
        // 新增校验逻辑（排除自身）
        if (checkEquipConflict(equip.getBelongSuit(), equip.getBelong(), id)) {
            return Result.error("该套装的该部位只能添加一件装备");
        }
        return Result.success(equipService.updateById(equip));
    }


    /**
     * 查询所有Equip
     *
     * @return
     */
    @Operation(summary = "查询所有Equip")
    @GetMapping
    public Result findAll() {
        return Result.success(equipService.list());
    }


    /**
     * 获取单个
     *
     * @param id
     * @return
     */
    @Operation(summary = "获取单个")
    @GetMapping("/{id}")
    public Result findOne(@PathVariable Integer id) {
        return Result.success(equipService.getById(id));
    }


    @Operation(summary = "获取单个")
    @GetMapping("/echarts/{ids}")
    public Result findEcharts(@PathVariable String [] ids) {
        List<Equip> list = equipService.listByIds(Arrays.asList(ids));
        // 初始化总和对象
        EquipStats totalStats = new EquipStats();

        // 计算每个属性的总和
        for (Equip equip : list) {
            totalStats.setAggressivity(totalStats.getAggressivity() + equip.getAggressivity());
            totalStats.setCritical(totalStats.getCritical() + equip.getCritical());
            totalStats.setDefense(totalStats.getDefense() + equip.getDefense());
            totalStats.setMana(totalStats.getMana() + equip.getMana());
            totalStats.setFire(totalStats.getFire() + equip.getFire());
            totalStats.setIce(totalStats.getIce() + equip.getIce());
            totalStats.setDrug(totalStats.getDrug() + equip.getDrug());
            totalStats.setThunder(totalStats.getThunder() + equip.getThunder());
        }
        return Result.success(totalStats);
    }


    /**
     * 分页显示
     *
     * @param
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Operation(summary = "分页显示")
    @GetMapping("/page")
    public Result findPage(
            @RequestParam(required = false) Long suitId,
            @RequestParam(defaultValue = "") String name,
            @RequestParam(required = false) Integer belong,
            @RequestParam(required = false) Integer belongSuit,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {

        LambdaQueryWrapper<Equip> queryWrapper = new LambdaQueryWrapper<>();
        if (suitId != null) {
            queryWrapper.eq(Equip::getBelongSuit, suitId);
        }
        if (StrUtil.isNotEmpty(name)) {
            queryWrapper.like(Equip::getName, name);
        }
        if (belong != null) {
            queryWrapper.eq(Equip::getBelong, belong);
        }
        if (belongSuit != null) {
            queryWrapper.eq(Equip::getBelongSuit, belongSuit);
        }
        queryWrapper.orderByDesc(Equip::getId);
        return Result.success(equipService.page(new Page<>(pageNum, pageSize), queryWrapper));
    }


    /**
     * 单个删除
     *
     * @param id
     * @return
     */
    @Operation(summary = "单个删除")
    @DeleteMapping("/{id}")
    @Transactional
    public Result delete(@PathVariable Long id) {
        // 删除装备
        boolean isEquipDeleted = equipService.removeById(id);
        if (isEquipDeleted) {
            // 根据eid删除关联的个性属性
            LambdaQueryWrapper<Personality> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Personality::getEid, id);
            personalityService.remove(wrapper);
        }
        return Result.success(isEquipDeleted);
    }


    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @Operation(summary = "批量删除")
    @DeleteMapping("/batch/{ids}")
    @Transactional
    public Result deleteByIds(@PathVariable Long[] ids) {
        // 转换ID列表
        List<Long> idList = Arrays.asList(ids);
        // 批量删除装备
        boolean isEquipsDeleted = equipService.removeByIds(idList);
        if (isEquipsDeleted) {
            // 根据eid列表批量删除关联的个性属性
            LambdaQueryWrapper<Personality> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(Personality::getEid, idList);
            personalityService.remove(wrapper);
        }
        return Result.success(isEquipsDeleted);
    }


    /**
     * 批量导出
     * 使用的技术为alibaba下面的easyexcel
     * 写数据
     *
     * @param ids
     * @return
     */
    @Operation(summary = "批量导出")
    @GetMapping("/batch/export/{ids}")
    public void exportByIds(@PathVariable String[] ids, HttpServletResponse response) throws IOException {
        List<Equip> list = equipService.listByIds(Arrays.asList(ids));

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");

        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("equip导出数据", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), Equip.class).sheet("sheel1").doWrite(list);
    }


    /**
     * 批量导入
     * 使用的技术为alibaba下面的easyexcel
     * 读数据
     *
     * @param
     */
    @Operation(summary = "批量导入")
    @PostMapping("/batch/upload")
    public Result writeExcel(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), Equip.class, new PageReadListener<Equip>(dataList -> {
            dataList.forEach(entity -> equipService.save(entity.toBuilder().id(null).build()));
        })).sheet().doRead();
        return Result.success();
    }


    @Operation(summary = "批量获取装备")
    @GetMapping("/batch/{ids}")
    public Result getBatchEquips(@PathVariable String[] ids) {
        List<Equip> list = equipService.listByIds(Arrays.asList(ids));
        return Result.success(list);
    }


    /**
     * 检查套装部件
     *
     * @param
     */
    private boolean checkEquipConflict(Long suitId, Integer belongType, Long excludeId) {
        LambdaQueryWrapper<Equip> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Equip::getBelongSuit, suitId)
                .eq(Equip::getBelong, belongType);

        if (excludeId != null) {
            queryWrapper.ne(Equip::getId, excludeId);
        }

        return equipService.count(queryWrapper) > 0;
    }
}